package com.rabincorp.facepoll.domain.services.impl;

import com.rabincorp.facepoll.domain.services.GenericDAO;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.orm.jpa.JpaTemplate;

/**
 *
 * @author isakrabin
 */
public abstract class GenericDAOImpl<T extends Serializable> implements GenericDAO<T> {
    
    protected static final Logger LOGGER = Logger.getLogger(GenericDAOImpl.class.getName());

    private Class<T> entityClass;
    
    protected JpaTemplate jpaTemplate;

    public GenericDAOImpl(JpaTemplate jpaTemplate) {
        this.jpaTemplate = jpaTemplate;

        ParameterizedType genericSuperClass = (ParameterizedType) (getClass().getGenericSuperclass());
        this.entityClass = (Class) genericSuperClass.getActualTypeArguments()[0];
    }

    @Override
    public T findByIndexId(Long indexId) {
        return jpaTemplate.find(entityClass, indexId);
    }

    @Override
    public List findByNamedQuery(String queryName) {
        return (List) jpaTemplate.findByNamedQuery(queryName);
    }

    @Override
    public List findByNamedQueryAndParams(String queryName, Object... params) {
        return (List) jpaTemplate.findByNamedQuery(queryName, params);
    }

    @Override
    public T findUniqueByNamedQuery(String queryName) {
        List results = findByNamedQuery(queryName);
        if (results.isEmpty()) {
            return null;
        } else {
            return (T) results.get(0);
        }
    }

    @Override
    public T findUniqueByNamedQueryAndParams(String queryName, Object... params) {
        List results = findByNamedQueryAndParams(queryName, params);
        if (results.isEmpty()) {
            return null;
        } else {
            return (T) results.get(0);
        }
    }

    @Override
    public T merge(T persistentEntity) {
        return jpaTemplate.merge(persistentEntity);
    }

    @Override
    public T refresh(T persistentEntity) {
        jpaTemplate.refresh(persistentEntity);
        return persistentEntity;
    }

    @Override
    public void remove(T persistentEntity) {
        jpaTemplate.remove(persistentEntity);
    }

    @Override
    public void save(T persistentEntity) {
        LOGGER.log(Level.INFO, "Saving entity {0}", persistentEntity.getClass().getName());
        jpaTemplate.persist(persistentEntity);
        LOGGER.log(Level.INFO, "Entity {0} has successfully saved.", persistentEntity.getClass().getName());
    }
}
